package com.itheima.reflect1;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Demo2 {

    // 获取类的信息

    @Test
    public void getClassInfo() {

        //1. 反射第一步，获取Class对象，代表拿到类
        Class c1 = Student.class;
        System.out.println(c1.getName());       //类的全类名 com.itheima.reflect1.Student
        System.out.println(c1.getSimpleName());     //类名 Student
    }

    //获取类的构造器对象并对其进行操作
    @Test
    public void getConstructorInfo() throws Exception {
        // 1.获取Class对象
        Class c1 = Teacher.class;
        // 2.获取构造器对象
        Constructor[] cons = c1.getDeclaredConstructors();
        for (Constructor con : cons) {
            System.out.println(con.getName() + " " + con.getParameterCount());      //参数个数
        }
        System.out.println("------------------------------------------------");
        //获取单个构造器对象
        Constructor con1 = c1.getDeclaredConstructor();      //无参构造器
        System.out.println(con1.getName() + " " + con1.getParameterCount());
        Constructor con2 = c1.getDeclaredConstructor(String.class, int.class);
        System.out.println(con2.getName() + " " + con2.getParameterCount());

        //获取构造器的作用：依然是创建对象
        //暴力反射：可以访问私有的属性、方法、构造器
        con1.setAccessible(true);       //绕过访问权限，直接访问
        Teacher t1 = (Teacher) con1.newInstance();
        System.out.println(t1);

        Teacher t2 = (Teacher) con2.newInstance("张三", 20);
        System.out.println(t2);
    }

    //获取类的成员变量对象并对其进行操作
    @Test
    public void getFieldInfo() throws Exception {
        // 1.获取Class对象
        Class c1 = Teacher.class;
        // 2.获取成员变量对象
        Field[] fields = c1.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName() + " " + field.getType().getName());
        }
        System.out.println("------------------------------------------------");
        //获取单个成员变量对象
        Field field1 = c1.getDeclaredField("gender");
        System.out.println(field1.getName() + " " + field1.getType().getName());
        Field field2 = c1.getDeclaredField("age");
        System.out.println(field2.getName() + " " + field2.getType().getName());

        //获取成员变量的作用：依然是取值和赋值
        Teacher t1 = new Teacher("张三", 20);
        field1.setAccessible(true);     //绕过访问权限，直接访问
        field1.set(t1, "男");        //相当于t1.setGender("男");    有特殊作用
        System.out.println(t1);

        String gender = (String) field1.get(t1);       //相当于String gender = t1.getGender();
        System.out.println(gender);
    }

    //获取类的成员方法对象并对其进行操作
    @Test
    public void getMethodInfo() throws Exception {
        // 1.获取Class对象
        Class c1 = Teacher.class;
        // 2.获取成员方法对象
        Method[] methods = c1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName() + " " + method.getParameterCount());
        }
        System.out.println("------------------------------------------------");
        //获取单个成员方法对象
        Method method1 = c1.getDeclaredMethod("show");
        System.out.println(method1.getName() + " " + method1.getParameterCount());
        Method method2 = c1.getDeclaredMethod("show1", String.class);
        System.out.println(method2.getName() + " " + method2.getParameterCount());

        //获取成员方法的作用：依然是调用方法
        Teacher t1 = new Teacher("张三", 20);
        method1.setAccessible(true);
        Object rs1 = method1.invoke(t1);
        System.out.println(rs1);

        Object rs2 = method2.invoke(t1, "张三");
        System.out.println(rs2);
    }
}
